﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.Core.Components
 * 唯一标识：50d5b427-5ad9-4f61-9735-08d87527f29b
 * 文件名：VampirewalCoreEventAggregatorService
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2025/6/12 17:18:07
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Vampirewal.Core.Components;

/// <summary>
/// 事件聚合器
/// </summary>
internal partial class VampirewalCoreEventAggregatorService : IVampirewalCoreEventAggregatorService
{
    /// <summary>
    /// 构造函数
    /// </summary>
    public VampirewalCoreEventAggregatorService()
    {
    }

    private readonly ConcurrentDictionary<Type, List<HandlerWrapper>> _handlers = new();

    /// <summary>
    /// 订阅事件（支持弱引用防止内存泄漏）
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="handler"></param>
    /// <param name="useWeakReference"></param>
    /// <returns></returns>
    public SubscriptionToken Subscribe<T>(Action<T> handler, bool useWeakReference = true)
    {
        var type = typeof(T);
        var token = new SubscriptionToken();
        var wrapper = new HandlerWrapper(handler, useWeakReference, token);

        if (!_handlers.ContainsKey(type))
        {
            _handlers[type] = new List<HandlerWrapper>();
        }

        _handlers[type].Add(wrapper);
        return token;
    }

    /// <summary>
    /// 取消订阅（通过 Token 控制）
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="token"></param>
    public void Unsubscribe<T>(SubscriptionToken token)
    {
        var type = typeof(T);
        if (_handlers.TryGetValue(type, out var handlers))
        {
            handlers.RemoveAll(h => h.Token == token);
        }
    }

    /// <summary>
    /// 异步发布事件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="message"></param>
    /// <returns></returns>
    public async Task PublishAsync<T>(T message, Action<Exception> exception = null)
    {
        var type = typeof(T);

        if (_handlers.TryGetValue(type, out var handlers))
        {
            foreach (var handler in handlers.ToList()) // 防止并发修改
            {
                if (handler.TryGetHandler(out var action))
                {
                    try
                    {
                        await Task.Run(() => action.DynamicInvoke(message));
                    }
                    catch (Exception ex)
                    {
                        exception?.Invoke(ex);
                        //_logger.Log($"Error handling event: {ex.Message}");
                    }
                }
            }
        }
    }

    /// <summary>
    /// 同步发布事件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    public void Publish<T>(T message, Action<Exception> exception = null)
    {
        var type = typeof(T);
        //_logger.Log($"Publishing event: {type.Name}");

        if (_handlers.TryGetValue(type, out var handlers))
        {
            foreach (var handler in handlers.ToList())
            {
                if (handler.TryGetHandler(out var action))
                {
                    try
                    {
                        action.DynamicInvoke(message);
                    }
                    catch (Exception ex)
                    {
                        exception?.Invoke(ex);
                        //_logger.Log($"Error handling event: {ex.Message}");
                    }
                }
            }
        }
    }

    /// <summary>
    /// 事件过滤订阅（按条件筛选）
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="filter"></param>
    /// <param name="handler"></param>
    /// <returns></returns>
    public SubscriptionToken SubscribeWithFilter<T>(Func<T, bool> filter, Action<T> handler)
    {
        var wrappedHandler = new Action<T>(msg =>
        {
            if (filter(msg))
            {
                handler(msg);
            }
        });
        return Subscribe(wrappedHandler);
    }
}

/// <summary>
/// 包装器：支持弱引用和 Token 管理
/// </summary>
internal class HandlerWrapper
{
    private readonly WeakReference _handlerRef;
    public SubscriptionToken Token { get; }

    public HandlerWrapper(Delegate handler, bool useWeakReference, SubscriptionToken token)
    {
        _handlerRef = useWeakReference ? new WeakReference(handler) : new WeakReference(handler);
        Token = token;
    }

    public bool TryGetHandler(out Delegate handler)
    {
        handler = _handlerRef.Target as Delegate;
        return handler != null;
    }
}

/// <summary>
/// 订阅令牌：用于取消订阅
/// </summary>
public class SubscriptionToken
{
    public Guid Id { get; } = Guid.NewGuid();
}